<?php
namespace app\api\controller\plan;

use addons\wanlshop\library\WanlPay\ProfitSharingCurl;
use addons\wanlshop\library\WanlPay\ProfitSharingSign;
use app\api\model\wanlshop\OrderGoods;
use app\api\model\wanlshop\PayOutTrade;
use app\common\controller\Api;
use think\Db;
use think\Exception;
use think\Request;

class Fitsharing
{
    private $wxConfig = null;
    private $sign = null;
    private $curl = null;

    public function __construct(Request $request = null)
    {
        $this->curl = new ProfitSharingCurl();
        $this->sign = new ProfitSharingSign();
        $this->wxConfig = $this->wxConfig();
    }


    // 查询未处理的分账订单
    public function order()
    {
        // 获取需要分账的订单
        $order = (new PayOutTrade())
            // 支付订单不为空 已支付
            ->whereNotNull('transaction_id')
            // 有分账信息的
            ->where('profit_sharing_id','>',0)
            // 待分账
            ->where('state' ,0)
            ->where('status' ,'normal')
            ->limit(0,300)
            ->select();
        // 分账
        foreach ($order as $item){
            $this->division_of_accounts($item);
        }
    }
    
    // 开始分账
    public function division_of_accounts($order)
    {
        // 分账配置
        $receivers = [];
        $data = [];
        $order_no = md5(time() . rand(1000, 9999));
        $time = time();
        // 根据订单信息获取 分账信息
        $invest_apply_for = Db::name('invest_apply_for')->where('id',$order['profit_sharing_id'])->find();
        // 获取订单商品ID
        $goods_id = (new OrderGoods())->where('order_id',$order['order_id'])->value('goods_id');
        // 判断是否有推荐人
        $Referrer_benefits = 0;
        // 有推荐人设置推荐人收益
        // 设置平台收益
        $amount = floor($order['price'] * $invest_apply_for['platform_proportion'] *100) - $Referrer_benefits;
        $receivers[] = array(
            'type'=>'PERSONAL_OPENID',
            'account'=>'ozawL5Ie8JivCe6XhBdw1nIWpX7E',
            'amount'=> $amount,
            'description'=>"商品平台分成",
        );
        // 判断投资人类型
        if ($invest_apply_for['is_invest'] == "invest"){
            // 第三方投资人投资
            // 根据投资人ID获取 投资人收款信息
            $wechat_pay = Db::name('user_wechat_pay')->where('user_id',$invest_apply_for['user_id'])->find();
            $amount = 0;
            $amount = floor($order['price'] * 100 * $invest_apply_for['investment_proportion']);
            if ($wechat_pay && $amount > 0){
                $receivers[] = array(
                    'type'=>$wechat_pay['type'],
                    'account'=>$wechat_pay['mch_id'],
                    'amount'=> $amount,
                    'description'=>"商品平台分成",
                );
                $data[] = [
                    'pay_out_trade_id' => $order['id'],
                    'order_no' => $order_no,
                    'user_id' => $wechat_pay['user_id'],
                    'goods_id' => $goods_id,
                    'apply_id' => $order['profit_sharing_id'],
                    'revenue' => $amount/100,
                    'createtime' => $time,
                    'updatetime' => $time,
                ];
            }
        }
        // 发起分账
        $receivers = json_encode($receivers,JSON_UNESCAPED_UNICODE);

        // 获取商家支付信息
        $shop_pay_info = Db::name('user_wechat_pay')->where(['user_id'=>$invest_apply_for['shop_user_id']])->find();

        $postArr = array(
            'appid'=>'wx0b5509f48f674fc5',
            'mch_id'=>$shop_pay_info['mch_id'],
            'nonce_str'=>$order_no,
            'transaction_id'=>$order['transaction_id'],
            'out_order_no'=>$order['out_trade_no'],
            'receivers'=>$receivers,
        );
        $sign = $this->sign->getSign($postArr, 'HMAC-SHA256',$shop_pay_info['secret_key']);
        $postArr['sign'] = $sign;

        //3.发送请求
        $url = 'https://api.mch.weixin.qq.com/secapi/pay/profitsharing';
        $postXML = $this->toXml($postArr);

        $opts = array(
            CURLOPT_HEADER    => 0,
            CURLOPT_SSL_VERIFYHOST    => false,
            CURLOPT_SSLCERTTYPE   => 'PEM', //默认支持的证书的类型，可以注释
            CURLOPT_SSLCERT   => $_SERVER['DOCUMENT_ROOT'].$shop_pay_info['certfile'],
            CURLOPT_SSLKEY    => $_SERVER['DOCUMENT_ROOT'].$shop_pay_info['keyfile'],
        );

        $curl_res = $this->curl->setOption($opts)->post($url,$postXML);

        $ret = $this->toArray($curl_res);
        var_dump($ret);
        $PayOutTrade = (new PayOutTrade())->where('id',$order['id'])->find();
        // 判断分账结果
        if ($ret['return_code']=='SUCCESS' and $ret['result_code']=='SUCCESS'){
            // 修改分账订单信息
            $PayOutTrade->state = 1;
            $PayOutTrade->memo = '分账成功~';
            $PayOutTrade->save();

            // 添加用户收益记录
            Db::name('accumulated_income')->insertAll($data);
            // 添加累计收益
            foreach ($data as $datum){
                Db::name('user')->where('id',$datum['user_id'])->setInc('revenue',$datum['revenue']);
            }

        }else{
            // 分账失败
            // 修改分账订单信息
            $PayOutTrade->state = -1;
            $PayOutTrade->memo = isset($ret['return_msg'])?$ret['return_msg']:$ret['err_code_des'];
            $PayOutTrade->save();
        }
        // 分账完成
    }

    /**
     *
    $wxConfig['app_id'] = '';//服务商公众号AppID
    $wxConfig['mch_id'] = ''; //服务商商户号
    $wxConfig['sub_app_id'] = '';//todo 子服务商公众号AppID
    $wxConfig['sub_mch_id'] = ''; //todo 子服务商商户号
    $wxConfig['md5_key'] = ''; //md5 秘钥
    $wxConfig['app_cert_pem'] = '';//证书路径
    $wxConfig['app_key_pem'] = '';//证书路径

     * @function 发起请求所必须的配置参数
     * @return mixed
     */
    private function wxConfig()
    {
//        $config = get_addon_config('wanlshop');
        $wxConfig = [
            'app_id'     => '', // 公众号 APPID
            'mch_id'     => '',
            'md5_key'        => '',
            'app_cert_pem' => ADDON_PATH.'bc26update' .DS. 'apiclient_cert.pem', // optional, 退款，红包等情况时需要用到
            'app_key_pem' => ADDON_PATH.'bc26update'  .DS. 'apiclient_key.pem',// optional, 退款，红包等情况时需要用到
        ];
        return $wxConfig;
    }

    // 添加一个分账账户
    public function addAccount()
    {
        //1.接收分账账户
        $receiver = array(
            'type'=>'PERSONAL_OPENID',
            'account'=>'ozawL5Ie8JivCe6XhBdw1nIWpX7E',
            'name'=>'',
            'relation_type'=>'USER',
        );
        $receiver = json_encode($receiver,JSON_UNESCAPED_UNICODE);

        //2.生成签名
        $postArr = array(
            'appid'=>'wx0b5509f48f674fc5',
            'mch_id'=>'1639993260',
            'nonce_str'=>md5(time() . rand(1000, 9999)),
            'receiver'=>$receiver
        );

        $sign = $this->sign->getSign($postArr, 'HMAC-SHA256','Sdchungunke1593deikldxldokdesmgd');
        $postArr['sign'] = $sign;
        //3.发送请求
        $url = 'https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver';
        $postXML = $this->toXml($postArr);
        $curl_res = $this->curl->post($url,$postXML);
        $ret = $this->toArray($curl_res);
        var_dump($ret);
//        return $ret;
    }

    public function testf()
    {
        $order_no = "4200002028202310209496828033";

        $receivers = [];

        $receivers[] = array(
            'type'=>'PERSONAL_OPENID',
            'account'=>'ozawL5Ie8JivCe6XhBdw1nIWpX7E',
            'amount'=>2,
            'description'=>"商品平台分成",
        );
//        $receivers[] = array(
//            'type'=>'MERCHANT_ID',
//            'account'=>'1639993260',
//            'amount'=>8,
//            'description'=>"商品平台分成",
//        );

        $receivers = json_encode($receivers,JSON_UNESCAPED_UNICODE);

        $postArr = array(
            'appid'=>'wx0b5509f48f674fc5',
            'mch_id'=>"1639993260",
//                'sub_mch_id'=>$this->wxConfig['sub_mch_id'],
//                'sub_appid'=>$this->wxConfig['sub_app_id'],
            'nonce_str'=>md5(time() . rand(1000, 9999)),
            'transaction_id'=>$order_no,
            'out_order_no'=>"P20150806125346777",
            'receivers'=>$receivers,
        );

        $sign = $this->sign->getSign($postArr, 'HMAC-SHA256','Sdchungunke1593deikldxldokdesmgd');
        $postArr['sign'] = $sign;

        //3.发送请求
        $url = 'https://api.mch.weixin.qq.com/secapi/pay/profitsharing';
        $postXML = $this->toXml($postArr);


        $opts = array(
            CURLOPT_HEADER    => 0,
            CURLOPT_SSL_VERIFYHOST    => false,
            CURLOPT_SSLCERTTYPE   => 'PEM', //默认支持的证书的类型，可以注释
//            CURLOPT_SSLCERT   => ADDON_PATH.'/wanlshop/certs/apiclient_cert.pem',
//            CURLOPT_SSLKEY    => ADDON_PATH.'/wanlshop/certs/apiclient_key.pem',
            CURLOPT_SSLCERT   => $_SERVER['DOCUMENT_ROOT'].'/uploads/20231026/d5caee200adbf128d48be15adf706b05.pem',
            CURLOPT_SSLKEY    => $_SERVER['DOCUMENT_ROOT'].'/uploads/20231026/c262893c14e15b184c3799736e7f2b50.pem',
        );

        $curl_res = $this->curl->setOption($opts)->post($url,$postXML);

        $ret = $this->toArray($curl_res);

        var_dump($ret);
    }

    // 添加分账方
    public function add($profitSharingAccount)
    {
        //1.接收分账账户
        $receiver = array(
            'type'=>$profitSharingAccount['type'],
            'account'=>$profitSharingAccount['account'],
            'name'=>$profitSharingAccount['name'],
            'relation_type'=>$profitSharingAccount['relation_type'],
        );
        $receiver = json_encode($receiver,JSON_UNESCAPED_UNICODE);

        //2.生成签名
        $postArr = array(
            'appid'=>$this->wxConfig['app_id'],
            'mch_id'=>$this->wxConfig['mch_id'],
//            'sub_mch_id'=>$this->wxConfig['sub_mch_id'],
//            'sub_appid'=>$this->wxConfig['sub_app_id'],
            'nonce_str'=>md5(time() . rand(1000, 9999)),
            'receiver'=>$receiver
        );

        $sign = $this->sign->getSign($postArr, 'HMAC-SHA256',$this->wxConfig['md5_key']);
        $postArr['sign'] = $sign;

        //3.发送请求
        $url = 'https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver';
        $postXML = $this->toXml($postArr);
//        Ilog::DEBUG("addReceiver.postXML: " . $postXML);

        $curl_res = $this->curl->post($url,$postXML);
//        Ilog::DEBUG("addReceiver.curl_res: " . $curl_res);

        $ret = $this->toArray($curl_res);
        return $ret;
    }

    /**
     * @function 删除分账接收方
     * @param $profitSharingAccount array 分账接收方
     * @return array|false
     * @throws Exception
     */
    public function removeReceiver($profitSharingAccount)
    {
        //1.接收分账账户
        $receiver = array(
            'type'=>$profitSharingAccount['type'],
            'account'=>$profitSharingAccount['account'],
            'name'=>$profitSharingAccount['name'],
        );
        $receiver = json_encode($receiver,JSON_UNESCAPED_UNICODE);

        //2.生成签名
        $postArr = array(
            'appid'=>$this->wxConfig['app_id'],
            'mch_id'=>$this->wxConfig['mch_id'],
            'sub_mch_id'=>$this->wxConfig['sub_mch_id'],
            'sub_appid'=>$this->wxConfig['sub_app_id'],
            'nonce_str'=>md5(time() . rand(1000, 9999)),
            'receiver'=>$receiver
        );

        $sign = $this->sign->getSign($postArr, 'HMAC-SHA256',$this->wxConfig['md5_key']);
        $postArr['sign'] = $sign;


        //3.发送请求
        $url = 'https://api.mch.weixin.qq.com/pay/profitsharingremovereceiver';
        $postXML = $this->toXml($postArr);
        Ilog::DEBUG("removeReceiver.postXML: " . $postXML);

        $curl_res = $this->curl->post($url,$postXML);
        Ilog::DEBUG("removeReceiver.curl_res: " . $curl_res);

        $ret = $this->toArray($curl_res);
        return $ret;
    }

    // 发起分账
    public function profitSharing($profitSharingOrders,$profitSharingAccounts)
    {
        if(empty($profitSharingOrders)){
            throw new Exception('没有待分帐订单');
        }
        if(empty($profitSharingAccounts)){
            throw new Exception('接收分账账户为空');
        }

        //1.设置分账账号
        $receivers = array();
        foreach ($profitSharingAccounts as $profitSharingAccount)
        {
            $tmp = array(
                'type'=>$profitSharingAccount['type'],
                'account'=>$profitSharingAccount['account'],
                'amount'=>intval($profitSharingAccount['amount']),
                'description'=>$profitSharingAccount['desc'],
            );
            $receivers[] = $tmp;
        }
        $receivers = json_encode($receivers,JSON_UNESCAPED_UNICODE);

        $totalCount = count($profitSharingOrders);
        $successCount = 0;
        $failCount = 0;
        $now = time();

        foreach ($profitSharingOrders as $profitSharingOrder)
        {
            //2.生成签名
            $postArr = array(
                'appid'=>$this->wxConfig['app_id'],
                'mch_id'=>$this->wxConfig['mch_id'],
//                'sub_mch_id'=>$this->wxConfig['sub_mch_id'],
//                'sub_appid'=>$this->wxConfig['sub_app_id'],
                'nonce_str'=>md5(time() . rand(1000, 9999)),
                'transaction_id'=>$profitSharingOrder['trans_id'],
                'out_order_no'=>$profitSharingOrder['order_no'].$profitSharingOrder['ticket_no'],
                'receivers'=>$receivers,
            );

            $sign = $this->sign->getSign($postArr, 'HMAC-SHA256',$this->wxConfig['md5_key']);
            $postArr['sign'] = $sign;

            //3.发送请求
            $url = 'https://api.mch.weixin.qq.com/secapi/pay/profitsharing';
            $postXML = $this->toXml($postArr);

            $opts = array(
                CURLOPT_HEADER    => 0,
                CURLOPT_SSL_VERIFYHOST    => false,
                CURLOPT_SSLCERTTYPE   => 'PEM', //默认支持的证书的类型，可以注释
                CURLOPT_SSLCERT   => $this->wxConfig['app_cert_pem'],
                CURLOPT_SSLKEY    => $this->wxConfig['app_key_pem'],
            );

            $curl_res = $this->curl->setOption($opts)->post($url,$postXML);

            $ret = $this->toArray($curl_res);

            if($ret['return_code']=='SUCCESS' and $ret['result_code']=='SUCCESS')
            {
                //更新分账订单状态
                $data['memo'] = '分账成功~';
                $data['status'] = 'done';
                model('app\admin\model\wanlshop\Profitorder')
                    ->where([
                        'order_no'=>$profitSharingOrder['order_no'],
                        'transaction_id'=>$profitSharingOrder['trans_id'],
                    ])
                    ->update($data);
                $successCount++;

            }else{
                //更新分账订单状态
                $data['memo'] = isset($ret['return_msg'])?$ret['return_msg']:$ret['err_code_des'];
//                $data['status'] = 'failed';
                model('app\admin\model\wanlshop\Profitorder')
                    ->where([
                        'order_no'=>$profitSharingOrder['order_no'],
                        'transaction_id'=>$profitSharingOrder['trans_id'],
                    ])
                    ->update($data);

                $failCount++;
            }

        }

        return array('processTime'=>date('Y-m-d H:i:s',$now),'totalCount'=>$totalCount,'successCount'=>$successCount,'failCount'=>$failCount);

    }

    /**
     * 分账
     * @param $payOrder 单条支付信息
     * @return void
     */
    public function profit_sharing($payOrder)
    {
        // 资方 + 平台分成
        $total = 0;
        // 根据支付信息获取分账用户
        $profit_sharing_id = $payOrder['profit_sharing_id'];
        $invest_apply_for = Db::name('invest_apply_for')->where('id',$profit_sharing_id)->find();

        // 配置分账用户
        $receivers = [];
        // 平台账户
        $receivers[] = array(
            'type'=>'MERCHANT_ID',
            'account'=>'',
            'amount'=>intval($invest_apply_for['platform_proportion'] * $payOrder['price'] * 100),
            'description'=>"商品平台分成".$payOrder['id'],
        );
        $total += intval($invest_apply_for['platform_proportion'] * $payOrder['price'] * 100);
        // 配置资方账户
        if ($invest_apply_for['is_invest'] == "invest"){
            // 根据资方id获取收款配置
            $i_config = Db::name('user_wechat_pay')->where('user_id',$invest_apply_for['user_id'])->find();
            $receivers[] = array(
                'type'=>$i_config['type'],
                'account'=>$i_config['mch_id'],
                'amount'=>intval($invest_apply_for['investment_proportion	'] * $payOrder['price'] * 100),
                'description'=>"商品资方分成".$payOrder['id'],
            );
            $total += intval($invest_apply_for['investment_proportion	'] * $payOrder['price'] * 100);
        }
        // 配置商家账户
        $shop_config = Db::name('user_wechat_pay')->where('shop_id',$invest_apply_for['shop_id'])->find();
        $receivers[] = array(
            'type'=>$shop_config['type'],
            'account'=>$shop_config['mch_id'],
            'amount'=>intval($payOrder['price'] * 100) - $total,
            'description'=>"商品资方分成".$payOrder['id'],
        );

        $receivers = json_encode($receivers,JSON_UNESCAPED_UNICODE);

        $totalCount = count($payOrder);
        $successCount = 0;
        $failCount = 0;
        $now = time();

        $postArr = array(
            'appid'=>$this->wxConfig['app_id'],
            'mch_id'=>$shop_config['mch_id'],
//                'sub_mch_id'=>$this->wxConfig['sub_mch_id'],
//                'sub_appid'=>$this->wxConfig['sub_app_id'],
            'nonce_str'=>md5(time() . rand(1000, 9999)),
            'transaction_id'=>$payOrder['transaction_id'],
            'out_order_no'=>$payOrder['out_trade_no'],
            'receivers'=>$receivers,
        );

        $sign = $this->sign->getSign($postArr, 'HMAC-SHA256',$this->wxConfig['md5_key']);
        $postArr['sign'] = $sign;

        //3.发送请求
        $url = 'https://api.mch.weixin.qq.com/secapi/pay/profitsharing';
        $postXML = $this->toXml($postArr);

        $opts = array(
            CURLOPT_HEADER    => 0,
            CURLOPT_SSL_VERIFYHOST    => false,
            CURLOPT_SSLCERTTYPE   => 'PEM', //默认支持的证书的类型，可以注释
            CURLOPT_SSLCERT   => $this->wxConfig['app_cert_pem'],
            CURLOPT_SSLKEY    => $this->wxConfig['app_key_pem'],
        );

        $curl_res = $this->curl->setOption($opts)->post($url,$postXML);

        $ret = $this->toArray($curl_res);

        if($ret['return_code']=='SUCCESS' and $ret['result_code']=='SUCCESS')
        {
            //更新分账订单状态
            $data['memo'] = '分账成功~';
            $data['state'] = 1;
            model('app\admin\model\wanlshop\PayOutTrade')
                ->where([
                    'id' => $payOrder['id']
                ])
                ->update($data);

            $successCount++;
        }else{
            //更新分账订单状态
            $data['memo'] = isset($ret['return_msg'])?$ret['return_msg']:$ret['err_code_des'];
            $data['state'] = -1;
            model('app\admin\model\wanlshop\PayOutTrade')
                ->where([
                    'id' => $payOrder['id']
                ])
                ->update($data);

            $successCount++;
        }

        return array('processTime'=>date('Y-m-d H:i:s',$now),'totalCount'=>$totalCount,'successCount'=>$successCount,'failCount'=>$failCount);
    }
    
    // 结束分账



    /**
     * @function 将array转为xml
     * @param array $values
     * @return string|bool
     * @author xiewg
     **/
    public function toXml($values)
    {
        if (!is_array($values) || count($values) <= 0) {
            return false;
        }

        $xml = "<xml>";
        foreach ($values as $key => $val) {
            if (is_numeric($val)) {
                $xml.="<".$key.">".$val."</".$key.">";
            } else {
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }

    /**
     * @function 将xml转为array
     * @param string $xml
     * @return array|false
     * @author xiewg
     */
    public function toArray($xml)
    {
        if (!$xml) {
            return false;
        }

        // 检查xml是否合法
        $xml_parser = xml_parser_create();
        if (!xml_parse($xml_parser, $xml, true)) {
            xml_parser_free($xml_parser);
            return false;
        }

        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);

        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

        return $data;
    }
}